/// 本文件由reazhuang@outlook.com开发编写 *CodeMaid自动格式化*
/// 设计为：绑定多选
///
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;

namespace ReaWTM.LayuiHelper
{
	/// <summary>
	/// 穿梭框
	/// </summary>
	[HtmlTargetElement("wt:transfer", Attributes = REQUIRED_ATTR_NAME, TagStructure = TagStructure.WithoutEndTag)]
	public class TransferTagHelper : BaseFieldTag
	{
		public string TextKey { get; set; } = "Text";

		public string ValueKey { get; set; } = "Value";
		/// <summary>
		/// 当数据在左右穿梭时触发，回调返回当前被穿梭的数据
		/// param0: 得到当前被穿梭的数据
		/// param1: 如果数据来自左边，index 为 0，否则为 1
		/// param2: 当前 transfer 实例
		/// </summary>
		public string ChangeFunc { get; set; }

		/// <summary>
		/// 启用搜索
		/// 默认 false
		/// </summary>
		public bool IsEnableSearch { get; set; } = true;

		/// <summary>
		/// 左侧穿梭框数据源
		/// </summary>
		public ModelExpression Items { get; set; }

		/// <summary>
		/// 左侧穿梭框上方标题
		/// </summary>
		public string LeftTitle { get; set; }

		/// <summary>
		/// 没有数据时的文案
		/// </summary>
		public string NonePlaceholder { get; set; } = THProgram._localizer["Sys.NoData"];

		/// <summary>
		/// 右侧穿梭框上方标题
		/// </summary>
		public string RightTitle { get; set; }

		/// <summary>
		/// 搜索无匹配数据时的文案
		/// </summary>
		public string SearchNonePlaceholder { get; set; } = THProgram._localizer["Sys.NoMatchingData"];

		public override void Process(TagHelperContext context, TagHelperOutput output)
		{
			if (Width == null) Width = 200;
			if (Height == null) Height = 340;
			output.TagName = "input";
			output.TagMode = TagMode.StartTagOnly;
			output.Attributes.Add("id", $"{Id}");
			output.Attributes.Add("wtm-ctype", "transfer");
			output.Attributes.Add("type", "hidden");

			StringBuilder builder = new StringBuilder();

			builder.Append($@"<div id='div{Id}'/>");

			builder.Append($@"
<script>
wtm.transfer_Render({{
id:'{Id}',
url:'{ItemUrl}',
value:'{GetDefaultValue()}',
data:{GetItems()},
showSearch:{GetBooleanString(IsEnableSearch)},
title:['{LeftTitle}','{RightTitle}'],
width:{Width},
height:{Height},
changeFunc:'{ChangeFunc}',
fieldName:'{GetName(context)}',
textKey:'{TextKey}',
valueKey:'{ValueKey}',
beforeMount:'{BeforeMount}',
mounted:'{Mounted}',
}});
</script>
");

			output.PostElement.AppendHtml(builder.ToString());
			base.Process(context, output);
		}

		protected override string GetDefaultValue()
		{
			if (Field?.Model != null)
			{
				DefaultValue = JsonSerializer.Serialize(Field.Model, JsonOptions2);
			}
			if (string.IsNullOrEmpty(DefaultValue)) return "[]";
			if (!DefaultValue.StartsWith("["))
			{
				DefaultValue = $"[{DefaultValue}]";
			}

			return DefaultValue;
		}

		protected override void SetName(TagHelperContext context, TagHelperOutput output)
		{ }

		private string GetItems()
		{
			if (!string.IsNullOrEmpty(ItemUrl)) return "[]";

			var modelType = Field.Metadata.ModelType;
			var listItems = new List<ComboSelectListItem>();
			if (Items?.Model == null)
			{
				if (modelType.IsList())
				{
					var innerType = modelType.GetGenericArguments()[0];
					if (innerType.IsEnumOrNullableEnum())
					{
						listItems = innerType.ToListItems();
					}
				}
				else if (modelType.IsBoolOrNullableBool())
				{
					listItems = new List<ComboSelectListItem>() { new ComboSelectListItem { Value = "true", Text = "|" } };
				}
			}
			else
			{
				if (typeof(IEnumerable<ComboSelectListItem>).IsAssignableFrom(Items.Metadata.ModelType))
				{
					if (typeof(IEnumerable<TreeSelectListItem>).IsAssignableFrom(Items.Metadata.ModelType))
					{
						listItems = (Items.Model as IEnumerable<TreeSelectListItem>).FlatTreeSelectList().Cast<ComboSelectListItem>().ToList();
					}
					else
					{
						listItems = (Items.Model as IEnumerable<ComboSelectListItem>).ToList();
					}
				}
				else if (Items.Metadata.ModelType.IsList())
				{
					var exports = (Items.Model as IList);
					foreach (var item in exports)
					{
						listItems.Add(new ComboSelectListItem
						{
							Text = item?.ToString(),
							Value = item?.ToString()
						});
					}
				}
			}
			return JsonSerializer.Serialize(listItems, JsonOptions2);
		}
	}
}